//
// Created by x on 2/4/24.
//

#include "mtcpserver.h"
#include <iostream>
#include <memory>
#include <string>
using std::cerr;
using std::endl;
using std::cout;
MTCPServer::MTCPServer(short port)
:port(port)
,acceptor_(io_context_, ip::tcp::endpoint(ip::tcp::v4(), port) )
{

}
void MTCPServer::startAccept() {

    socket_ = std::make_shared<MSocketTCP>(io_context_);
    clients_.push_back(socket_);

    thread_pool_ = std::make_shared<asio::thread_pool>(std::thread::hardware_concurrency()); // 创建6个线程的线程池
//// 在异步操作中使用线程池
    acceptor_.async_accept(*(clients_.back().get()),
         [&](const asio::error_code& error) {
             handleClient(socket_.get(), error);
              if(!error) {
//                  socket_->read();
                  asio::post(*(thread_pool_),[&]() {
                      auto it = clients_.rbegin();
                      ++it; // 移动到倒数第二个元素
                      auto s = *it;
                      s->read();
                  });

                  this->startAccept();
              }
              else {
                  cerr << "accept failed: " << error.message() << endl;
                  socket_->close();
              }
     });
}


/**
 *  handle client 处理错误
 * @param socket
 */
void MTCPServer::handleClient(tcp::socket* socket,const asio::error_code& error) {
    if(!error){
        cout<<"accept ok is "<<socket->is_open()<<socket->remote_endpoint()<<endl;
        write(socket, "connected ok");
    }
    else
    {
        cerr << "accept failed: " << error.message() << endl;
        socket->close();
    }

}

void MTCPServer::run() {
    try {
        startAccept();
        io_context_.run();
        cout<<"io_context_.run() end"<<endl;
    }
    catch  (std::exception& e){
        cerr << "Exception caught: " << e.what() << endl;
    }
}

void MTCPServer::printf_pool(thread_pool &pool) {

}

void MTCPServer::write(tcp::socket *socket, std::string str) {
    auto len = socket->write_some(asio::buffer(str));
    cout<<"["<<socket->remote_endpoint()<<"]:"<<str<<" len="<<len<<endl;
}

MTCPServer::~MTCPServer() = default;
